﻿using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using NET6.WebAPI.Controllers.Base;
using NET6.WebAPI.Dtos.Tool;
using NET6.WebAPI.Entities.Product;
using NET6.WebAPI.Enums;
using NET6.WebAPI.Exceptions;
using NET6.WebAPI.Extensions;
using NET6.WebAPI.Reqs.Base;
using NET6.WebAPI.Reqs.Product;
using NET6.WebAPI.Reqs.Tool;
using NET6.WebAPI.Strategies;
using SqlSugar;
using static NET6.WebAPI.Entities.Base.ExamineBase;

namespace NET6.WebAPI.Controllers
{
    //[Authorize]
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class BrandController : BusinessController
    {
        public BrandController(SqlSugarClient db, IMapper mapper) : base(db, mapper) { }

        [HttpPost]
        public async Task<IActionResult> ExamineList(PagingReq<Sys_BrandQueryReq> req)
        {
            var pageData = await _db.Queryable<Sys_Brand_Examine>()
                .Where(it => req.Body.ExamineStatusArray.Contains(it.ExamineStatus))
                .WhereIF(req.Body.Name.HasValue(), it => it.Name.Contains(req.Body.Name.Trim()))
                .OrderBy(it => it.ID, OrderByType.Desc)
                .GetPageListAsync(req.PageNumber, req.PageSize);

            return Ok(new HttpResponseDto(HttpResponseCode.QuerySuccess, pageData));
        }

        [HttpPost]
        public async Task<IActionResult> List(PagingReq<Sys_BrandQueryReq> req)
        {
            var pageData = await _db.Queryable<Sys_Brand>()
                .WhereIF(req.Body.Name.HasValue(), it => it.Name.Contains(req.Body.Name.Trim()))
                .OrderBy(it => it.ID, OrderByType.Desc)
                .GetPageListAsync(req.PageNumber, req.PageSize);

            return Ok(new HttpResponseDto(HttpResponseCode.QuerySuccess, pageData));
        }

        [HttpPost]
        public async Task<IActionResult> Add(Sys_BrandAddReq req)
        {
            await _db.Queryable<Sys_Brand>().CheckExistsAsync(it => it.Name == req.Name);

            var examine = _mapper.Map<Sys_Brand_Examine>(req);

            int id = await _db.Insertable(examine).ExecuteReturnIdentityAsync();
            return Ok(new HttpResponseDto(HttpResponseCode.InsertSuccess, id));
        }

        [HttpPost]
        public async Task<IActionResult> ExamineModify(Sys_BrandModifyReq req)
        {
            var examine = await _db.Queryable<Sys_Brand_Examine>().GetFirstAsync(it => it.ID == req.ID);

            // 如果不想手动映射就建一个专用请求模型
            examine.Name = req.Name;
            examine.Address = req.Address;
            examine.Website = req.Website;
            examine.Intro = req.Intro;

            await _db.Updateable(examine).ExecuteCommandAsync();
            return Ok(new HttpResponseDto(HttpResponseCode.ModifySuccess));
        }

        [HttpPost]
        public async Task<IActionResult> Modify(Sys_BrandModifyReq req)
        {
            await _db.Queryable<Sys_Brand>().CheckExistsAsync(it => it.ID == req.ID);

            // 名称重复检查(排除当前记录)
            await _db.Queryable<Sys_Brand>().CheckExistsAsync(it => it.Name == req.Name && it.ID != req.ID);

            var examine = _mapper.Map<Sys_Brand_Examine>(req);

            int id = await _db.Insertable(examine).ExecuteReturnIdentityAsync();
            return Ok(new HttpResponseDto(HttpResponseCode.ModifySuccess, id));
        }

        [HttpPost]
        public async Task<IActionResult> Delete(PrimaryKeyReq req)
        {
            var brand = await _db.Queryable<Sys_Brand>().GetFirstAsync(it => it.ID == req.ID);

            var examine = _mapper.Map<Sys_Brand_Examine>(brand);
            examine.ExamineType = ExamineTypeEnum.Delete;

            int id = await _db.Insertable(examine).ExecuteReturnIdentityAsync();
            return Ok(new HttpResponseDto(HttpResponseCode.DeleteSuccess, id));
        }

        [HttpPost]
        public async Task<IActionResult> Recover(PrimaryKeyReq req)
        {
            var brand = await _db.Queryable<Sys_Brand>().GetFirstAsync(it => it.ID == req.ID);

            var examine = _mapper.Map<Sys_Brand_Examine>(brand);
            examine.ExamineType = ExamineTypeEnum.Recover;

            int id = await _db.Insertable(examine).ExecuteReturnIdentityAsync();
            return Ok(new HttpResponseDto(HttpResponseCode.RecoverSuccess, id));
        }

        [HttpPost]
        public async Task<IActionResult> Resubmit(PrimaryKeyReq req)
        {
            var examine = await _db.Queryable<Sys_Brand_Examine>().GetFirstAsync(it => it.ID == req.ID);
            examine.ChcekExamineStatus(ExamineStatusEnum.Rejected);

            examine.ExamineStatus = ExamineStatusEnum.PendingApproval;
            examine.ExamineRemark = "";
            await _db.Updateable(examine).ExecuteCommandAsync();

            return Ok(new HttpResponseDto(HttpResponseCode.ResetSuccess));
        }

        [HttpPost]
        public async Task<IActionResult> Examine(ExamineReq req)
        {
            var examine = await _db.Queryable<Sys_Brand_Examine>().GetFirstAsync(it => it.ID == req.ID);

            // 检查记录是否为待审核状态
            examine.ChcekExamineStatus(ExamineStatusEnum.PendingApproval);

            // 使用策略
            IExamineStatusStrategy strategy;

            if (req.ExamineResult == ExamineResult.Approved)
            {
                examine.ExamineStatus = ExamineStatusEnum.Approved;
                examine.ExamineRemark = req.ExamineRemark;

                switch (examine.ExamineType)
                {
                    case ExamineTypeEnum.Add:

                        // 名称重复检查(拦截审核前修改)
                        await _db.Queryable<Sys_Brand>().CheckExistsAsync(it => it.Name == examine.Name);

                        strategy = new BrandAddStrategy();
                        break;

                    case ExamineTypeEnum.Modify:

                        // 名称重复检查(排除当前记录)
                        await _db.Queryable<Sys_Brand>()
                            .CheckExistsAsync(it => it.Name == examine.Name && it.ID != examine.BusinessID);

                        strategy = new BrandModifyStrategy();
                        break;

                    case ExamineTypeEnum.Delete:

                        strategy = new BrandDeleteStrategy();
                        break;

                    case ExamineTypeEnum.Recover:

                        strategy = new BrandRecoverStrategy();
                        break;

                    default:
                        throw new InvalidStatusException();
                }

                // 执行策略
                await strategy.Execute(_db, _mapper, examine);
            }
            else
            {
                examine.ExamineStatus = ExamineStatusEnum.Rejected;
                examine.ExamineRemark = req.ExamineRemark;
                await _db.Updateable(examine).ExecuteCommandAsync();
            }

            return Ok(new HttpResponseDto(HttpResponseCode.ExamineSuccess, examine.BusinessID.GetValue()));
        }
    }
}
